package com.c611.smartclassroom;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.aliyun.alink.dm.api.BaseInfo;
import com.aliyun.alink.dm.api.DeviceInfo;
import com.aliyun.alink.dm.api.InitResult;
import com.aliyun.alink.dm.api.SignUtils;
import com.aliyun.alink.dm.model.ResponseModel;
import com.aliyun.alink.linkkit.api.ILinkKitConnectListener;
import com.aliyun.alink.linkkit.api.IoTMqttClientConfig;
import com.aliyun.alink.linkkit.api.LinkKit;
import com.aliyun.alink.linkkit.api.LinkKitInitParams;
import com.aliyun.alink.linksdk.channel.gateway.api.subdevice.ISubDeviceActionListener;
import com.aliyun.alink.linksdk.channel.gateway.api.subdevice.ISubDeviceChannel;
import com.aliyun.alink.linksdk.channel.gateway.api.subdevice.ISubDeviceConnectListener;
import com.aliyun.alink.linksdk.cmp.core.base.AMessage;
import com.aliyun.alink.linksdk.cmp.core.base.ARequest;
import com.aliyun.alink.linksdk.cmp.core.base.AResponse;
import com.aliyun.alink.linksdk.cmp.core.listener.IConnectSendListener;
import com.aliyun.alink.linksdk.tools.AError;
import com.aliyun.alink.linksdk.tools.ALog;
import com.c611.smartclassroom.ali.lot.DeviceInfoData;
import com.c611.smartclassroom.ali.lot.FileUtils;
import com.google.gson.Gson;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.aliyun.alink.linksdk.tools.ALog.LEVEL_DEBUG;

@SpringBootApplication
@MapperScan(basePackages = "com.c611.smartclassroom.mapper")
@EnableCaching
public class SmartclassroomApplication {
    private static String regionId = "cn-shanghai";
    private static final String TAG = "TOPO";

    //网关设备三元组信息
    private static String GWproductKey = "a1kHSnudRcH";
    private static String GWdeviceName = "0FfIBd8UjA1Smy8pGwmY";
    private static String GWdeviceSecret = "Y0lYgLfdeeiokAGlILOwuuIzTxlPlCKO";

    public static void main(String[] args) {
        SpringApplication.run(SmartclassroomApplication.class, args);
/*
        ALog.d(TAG, "args=" + Arrays.toString(args));
        System.out.println(System.getProperty("user.dir"));

        *//**
         * mqtt连接信息
         *//*
        SmartclassroomApplication manager = new SmartclassroomApplication();

        *//**
         * 服务器端的java http 客户端使用TSLv1.2。
         *//*
        System.setProperty("https.protocols", "TLSv2");

        manager.init();*/
    }

    public void init() {
        LinkKitInitParams params = new LinkKitInitParams();
        /**
         * 设置 Mqtt 初始化参数
         */
        IoTMqttClientConfig config = new IoTMqttClientConfig();
        config.productKey = GWproductKey;
        config.deviceName = GWdeviceName;
        config.deviceSecret = GWdeviceSecret;
        config.channelHost = GWproductKey + ".iot-as-mqtt." + regionId + ".aliyuncs.com:1883";
        /**
         * 是否接受离线消息
         * 对应 mqtt 的 cleanSession 字段
         */
        config.receiveOfflineMsg = false;
        params.mqttClientConfig = config;
        ALog.setLevel(LEVEL_DEBUG);
        ALog.i(TAG, "mqtt connetcion info=" + params);

        /**
         * 设置初始化，传入设备证书信息
         */
        DeviceInfo deviceInfo = new DeviceInfo();
        deviceInfo.productKey = GWproductKey;
        deviceInfo.deviceName = GWdeviceName;
        deviceInfo.deviceSecret = GWdeviceSecret;
        params.deviceInfo = deviceInfo;

        /**建立链接**/
        LinkKit.getInstance().init(params, new ILinkKitConnectListener() {
            public void onError(AError aError) {
                ALog.e(TAG, "Init Error error=" + aError);
            }

            public void onInitDone(InitResult initResult) {
                ALog.i(TAG, "onInitDone result=" + initResult);

                //获取网关下topo关系，查询网关与子设备是否已经存在topo关系
                //如果已经存在，则直接上线子设备
                getGWDeviceTopo();


                //获取子设备信息的json
                //利用循环，多次调用上线

                String diPath = System.getProperty("user.dir") + "/subDevice_id.json";
                String subDeviceInfo = FileUtils.readFile(diPath);

                if (subDeviceInfo == null) {
                    ALog.e(TAG, "main - need device info path.");
                    return;
                }
                Gson mGson = new Gson();
                DeviceInfoData subDeviceInfoData = mGson.fromJson(subDeviceInfo, DeviceInfoData.class);

                if (subDeviceInfoData == null) {
                    ALog.e(TAG, "main - deviceInfo format error.");
                    return;
                }


                JSONObject array = JSON.parseObject(subDeviceInfo);
                for (String k : array.keySet()) {
                    JSONArray job = array.getJSONArray(k);
                    for (int i = 0; i < job.size(); i++) {
                        String productKey = job.getJSONObject(i).getString("productKey");
                        String deviceName = job.getJSONObject(i).getString("deviceName");
                        String deviceSecret = job.getJSONObject(i).getString("deviceSecret");
                        System.out.println(productKey);
                        System.out.println(deviceName);
                        System.out.println(deviceSecret);

                        //待添加拓扑关系 子设备信息
                        gatewayAddSubDevice(productKey,deviceName,deviceSecret);

                        //子设备上线
//                        gatewaySubDeviceLogin(productKey, deviceName);
                    }
                }

            }
        });
    }

    /**
     * 获取网关下topo关系，查询网关与自设备是否已经存在topo关系
     */
    private void getGWDeviceTopo() {
        System.out.println("获取网关topo关系");
        LinkKit.getInstance().getGateway().gatewayGetSubDevices(new IConnectSendListener() {

            @Override
            public void onResponse(ARequest request, AResponse aResponse) {
                ALog.i(TAG, "获取网关的topo关系成功 : " + JSONObject.toJSONString(aResponse));

                // 获取子设备列表结果
                try {
                    ResponseModel<List<DeviceInfo>> response = JSONObject.parseObject(aResponse.data.toString(), new TypeReference<ResponseModel<List<DeviceInfo>>>() {
                    }.getType());
                    // TODO 根据实际应用场景处理
                    Integer subDeviceCounts = response.data.size();
                    System.out.println("topo下子设备的数目：" + subDeviceCounts);// topo网管下子设备的数目

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onFailure(ARequest request, AError error) {
                ALog.i(TAG, "获取网关的topo关系失败 : " + JSONObject.toJSONString(error));
            }
        });
    }


    /**
     * 待添加拓扑关系 子设备信息
     */
    private void gatewayAddSubDevice(String productKey, String deviceName,String deviceSecret) {
        System.out.println("查看-----------------------");
        final BaseInfo baseInfo1 = new BaseInfo();
        baseInfo1.productKey = productKey;
        baseInfo1.deviceName = deviceName;

        LinkKit.getInstance().getGateway().gatewayAddSubDevice(baseInfo1, new ISubDeviceConnectListener() {
            @Override
            public String getSignMethod() {
                // 使用的签名方法
                return "hmacsha1";
            }

            @Override
            public String getSignValue() {
                // 获取签名，用户使用 deviceSecret 获得签名结果
                Map<String, String> signMap = new HashMap<>();
                signMap.put("productKey", baseInfo1.productKey);
                signMap.put("deviceName", baseInfo1.deviceName);
//                signMap.put("timestamp", String.valueOf(System.currentTimeMillis()));
                signMap.put("clientId", getClientId());
                return SignUtils.hmacSign(signMap, deviceSecret);
            }

            @Override
            public String getClientId() {
                // clientId 可为任意值
                return "id";
            }

            @Override
            public Map<String, Object> getSignExtraData() {
                return null;
            }

            @Override
            public void onConnectResult(boolean isSuccess, ISubDeviceChannel iSubDeviceChannel, AError aError) {


                // 添加结果
                if (isSuccess) {
                    // 子设备添加成功，接下来可以做子设备上线的逻辑
                    ALog.i(TAG, "topo关系添加成功 : " + JSONObject.toJSONString(iSubDeviceChannel));
                    //子设备上线
                    gatewaySubDeviceLogin(productKey, deviceName);
                } else {
                    ALog.i(TAG, "topo关系添加失败 : " + JSONObject.toJSONString(aError));
                }
            }

            @Override
            public void onDataPush(String s, AMessage aMessage) {

            }
        });
    }


    /**
     * 调用子设备上线之前，请确保已完成子设备添加。网关发现子设备连上网关之后，
     * 需要告知云端子设备上线，子设备上线之后可以执行子设备的订阅、发布等操作。
     */
    public void gatewaySubDeviceLogin(String productKey, String deviceName){
        System.out.println("登录");

        BaseInfo baseInfo1 = new BaseInfo();
        baseInfo1.productKey = productKey;
        baseInfo1.deviceName = deviceName;

        LinkKit.getInstance().getGateway().gatewaySubDeviceLogin(baseInfo1, new ISubDeviceActionListener() {
            @Override
            public void onSuccess() {
                System.out.println("成功");
                // 代理子设备上线成功
                // 上线之后可删除和禁用子设备
                // subDevDisable(null);
                // subDevDelete(null);
            }
            @Override
            public void onFailed(AError aError) {
                System.out.println("失败");
                ALog.d(TAG, "onFailed() called with: aError = [" + aError + "]");
            }
        });

    }

}



